package com.yuandian.business.monitor.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuandian.api.business_monitor.po.UsersOperationsParams;
import com.yuandian.api.business_monitor.vo.*;
import com.yuandian.api.business_monitor.vo.*;
import com.yuandian.api.management.entity.ConfBusiness;
import com.yuandian.api.management.entity.ConfSystem;
import com.yuandian.api.management.feign.RemoteBusinessService;
import com.yuandian.api.management.feign.RemoteExclusiveIndicatorService;
import com.yuandian.api.management.feign.RemoteSystemService;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.business.monitor.mapper.UserOperationsMapper;
import com.yuandian.business.monitor.service.IUserOperationsService;
import com.yuandian.po.BaseSearch;
import com.yuandian.utils.BeanUtils;
import com.yuandian.utils.PageDataInfo;
import com.yuandian.utils.YDateUtil;
import com.yuandian.utils.poi.ExcelTitleUtils;
import com.yuandian.utils.poi.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户信息查询
 * </p>
 *
 * @author zuokun
 * @since 2021-12-6
 */
@Service
@Slf4j
public class UserOperationsServiceImpl implements IUserOperationsService {
	@Autowired
	UserOperationsMapper userOperationsMapper;
	@Autowired
	private RemoteSystemService remoteSystemService;
	@Autowired
	private RemoteBusinessService remoteBusinessService;
	@Autowired
	private RemoteExclusiveIndicatorService remoteExclusiveIndicatorService;
	/**
	 * 查询用户操作概况
	 *
	 * @param params
	 * @return 通用分页对象
	 */
	@Override
	public PageDataInfo queryUsersOperationsOverview(UsersOperationsParams params) {
		//默认按访问量排序
		if (params.getOrderByColumn() == null || params.getOrderByColumn().equals("")) {
			params.setOrderByColumn("visitCount");
			params.setIsAsc("desc");
		}
		//如果集合大小为0,则赋值为null
		if (params.getBusinessCodes() == null || params.getBusinessCodes().size() == 0) {
			params.setBusinessCodes(null);
		}
		if (params.getRegionalCodes() == null || params.getRegionalCodes().size() == 0) {
			params.setRegionalCodes(null);
		}
		//创建分页对象,并设置页面大小和页数
		Page<UsersOperationsOverviewVO> page = new Page<>(params.getPageNum(), params.getPageSize());
		//调用查询用户操作统计方法
		List<UsersOperationsOverviewVO> usersOperationsOverviewVOS = null;
		usersOperationsOverviewVOS = userOperationsMapper.queryUsersOperationsOverview(page, params);
		//处理startTime和endTime格式并添加业务数
		// 返回分页对象
		return new PageDataInfo(page, usersOperationsOverviewVOS);
	}

	/**
	 * 查询XX用户操作统计
	 *
	 * @param params
	 * @return 通用分页对象
	 */
	@Override
	public PageDataInfo queryUserOperationsStatistics(UsersOperationsParams params) {
		//默认按访问量排序
		if (params.getOrderByColumn() == null || params.getOrderByColumn().equals("")) {
			params.setOrderByColumn("visitCount");
			params.setIsAsc("desc");
		}
		//如果集合大小为0,则赋值为null
		if (params.getBusinessCodes() != null && params.getBusinessCodes().size() == 0) {
			params.setBusinessCodes(null);
		}
		if (params.getRegionalCodes() != null && params.getRegionalCodes().size() == 0) {
			params.setRegionalCodes(null);
		}
		//创建分页对象,并设置页面大小和页数
		Page<UserOperationsStatisticsVO> page = new Page<>(params.getPageNum(), params.getPageSize());
		List<UserOperationsStatisticsVO> usersOperationsStatisticsVOS = null;
		usersOperationsStatisticsVOS = userOperationsMapper.queryUserOperationsStatistics(page, params);
		return new PageDataInfo(page, usersOperationsStatisticsVOS);
	}

	/**
	 * XX用户-XX业务-操作详情
	 *
	 * @param params
	 * @return 通用分页对象
	 */
	@Override
	public PageDataInfo queryUserBusinessOperationsDetail(UsersOperationsParams params) {
//        //1、用户业务操作详情对象集合
		List<UserBusinessOperationsDetailVO> userBusinessOperationsDetailVOS = new ArrayList<>();
		if (ObjectUtil.isEmpty(params.getOrderByColumn())) {
			params.setOrderByColumn("alarmCount");
			params.setIsAsc("desc");
		}
		//2、查询
		Page<UserOperationsStatisticsVO> page = new Page<>(params.getPageNum(), params.getPageSize());
		userBusinessOperationsDetailVOS = userOperationsMapper.queryUserBusinessOperationsDetail(page, params);
		// 3、处理结果
		for (UserBusinessOperationsDetailVO businessOperationsDetailVO : userBusinessOperationsDetailVOS) {
			String isDealFail = businessOperationsDetailVO.getIsDealFail();
			if (isDealFail.equals("1")) {
				businessOperationsDetailVO.setIsDealFail("失败");
			} else if (isDealFail.equals("0")) {
				businessOperationsDetailVO.setIsDealFail("成功");
			}
			String completionState = businessOperationsDetailVO.getCompletionState();
			if (completionState.equals("1")) {
				businessOperationsDetailVO.setCompletionState("完整");
			} else if (completionState.equals("0")) {
				businessOperationsDetailVO.setCompletionState("不完整");
			}
			Map<String, List<String>> businessIndicatorsShowMap = remoteExclusiveIndicatorService.getBusinessIndicatorsShowMap().getData();
			//根据配置处理专属指标是否显示
			String exclusiveIndicator = businessOperationsDetailVO.getExclusiveIndicator();
			businessOperationsDetailVO.setExclusiveIndicator(ExclusiveIndicator.getIndicatorWithSet(exclusiveIndicator, businessIndicatorsShowMap.get(businessOperationsDetailVO.getBusinessCode())));

		}
		return new PageDataInfo(page, userBusinessOperationsDetailVOS);
	}

	/**
	 * XXX用户操作轨迹
	 *
	 * @param params
	 * @return List
	 */
	@Override
	public Object queryUserOperationsTrajectory(UsersOperationsParams params) {
		//用户操作轨迹对象集合
		List<UserOperationsTrajectoryVO> userOperationsTrajectoryVOS = userOperationsMapper.queryUserOperationsTrajectory(params);
		return classifiedData(userOperationsTrajectoryVOS, params);
	}

	/**
	 * 对数据集按照业务进行分组
	 *
	 * @param list
	 * @param params
	 * @return
	 */
	private Object classifiedData(List<UserOperationsTrajectoryVO> list, UsersOperationsParams params) {

		if (list == null && list.size() == 0) {
			return null;
		}

		// 获取完整的时间刻度列表(主要要去除最后一个时间点, 因为SQL条件是: < endTime)
		List<String> timeList = YDateUtil.getTimeList(params.getStartTime(), params.getEndTime(), 1);
		List<String> timeResList = new ArrayList<>();
		timeList.remove(timeList.size() - 1);


		List<List<UserOperationsTrajectoryVO>> resList = new ArrayList<>();
		Map<String, List<UserOperationsTrajectoryVO>> map = new HashMap<>();

//         根据businessCode 进行分组
		if (list != null && list.size() > 0) {
			for (UserOperationsTrajectoryVO vo : list) {
				map.computeIfAbsent(vo.getBusinessCode(), k -> new ArrayList<>());
				map.get(vo.getBusinessCode()).add(vo);
			}
		}

		// 封装数据
		Iterator<Map.Entry<String, List<UserOperationsTrajectoryVO>>> it = map.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<String, List<UserOperationsTrajectoryVO>> entry = it.next();
			List<UserOperationsTrajectoryVO> valuelist = entry.getValue();
			resList.add(valuelist);
		}

		UserOperationsTrajectoryResVO trajectoryVo = new UserOperationsTrajectoryResVO();
		List<String> collect = resList.stream().map(s -> s.get(0).getStartTime()).sorted().collect(Collectors.toList());
		if (timeList != null && timeList.size() > 0) {
			for (String s : timeList) {
				if (s.compareTo(collect.get(0).substring(0, 17)) >= 0) {
					timeResList.add(s.substring(0, 19));
				}
			}
		}

		trajectoryVo.setLabelTimeList(timeResList);
		trajectoryVo.setResList(resList);

		return trajectoryVo;

	}


	/**
	 * 导出用户操作概况列表Excel文件
	 *
	 * @param params 用户操作统计查询参数
	 * @param
	 */
	@Override
	public void exportUsersOperationsOverview(UsersOperationsParams params, HttpServletResponse response) throws IOException {
		//取消分页
		params.setPageNum(1);
		params.setPageSize(-1);
		//查询数据
		List<UsersOperationsOverviewVO> usersOperationsOverviewVOS = new ArrayList<>();
		try {
			PageDataInfo pageDataInfo = queryUsersOperationsOverview(params);
			usersOperationsOverviewVOS = BeanUtils.cast(pageDataInfo.getData());
		} catch (Exception e) {
			log.error("查询的表不在保存周期或数据不存在");
		}
		//设置序号
		int index = 1;
		for (UsersOperationsOverviewVO vo : usersOperationsOverviewVOS) {
			DecimalFormat df = new DecimalFormat(".00");
			double dealTime = Double.parseDouble(vo.getDealTime());
			double avgDealTime = Double.parseDouble(vo.getAvgDealTime());
			double second = 0;
			int minute = 0;
			double ms = 0;
			//转化时间戳
			if (dealTime >= 60000000) {
				second = dealTime / 1000000;
				minute = (int) second / 60;
				second = second - minute * 60;
				vo.setDealTime(minute + "分" + df.format(second) + "秒");
			} else if (dealTime >= 1000000) {
				second = dealTime / 1000000;
				vo.setDealTime(df.format(second) + "秒");
			} else {
				ms = dealTime / 1000;
				vo.setDealTime(df.format(ms) + "毫秒");
			}
			if (avgDealTime >= 60000000) {
				second = avgDealTime / 1000000;
				minute = (int) second / 60;
				second = second - minute * 60;
				vo.setAvgDealTime(minute + "分" + df.format(second) + "秒");
			} else if (avgDealTime >= 1000000) {
				second = avgDealTime / 1000000;
				vo.setAvgDealTime(df.format(second) + "秒");
			} else {
				ms = avgDealTime / 1000;
				vo.setAvgDealTime(df.format(ms) + "毫秒");
			}
			//序号自增1
			vo.setId(index++);
		}
		//excel主标题
		String title = "用户操作概况";
		List<String> titleParams = new ArrayList<>();
		titleParams.add(title);
		ConfSystem system = remoteSystemService.getSystemById(params.getSystemId()).getData();
		if (ObjectUtil.isNotEmpty(system)) {
			titleParams.add(system.getName());
		}
		String formTitleName = ExcelTitleUtils.formTitleName(titleParams, params.getStartTime(), params.getEndTime());
		//列标题
		List<List<String>> headList = new ArrayList<>();
		List<String> titleList = Arrays.asList("序号", "用户标识", "用户名", "业务使用数量", "访问量", "告警访问量", "失败访问量", "开始时间", "结束时间", "总办理时长", "平均办理时长");
		titleList.forEach(s -> {
			List<String> childHeadList = new ArrayList<>();
			childHeadList.add(formTitleName);
			childHeadList.add(s);
			headList.add(childHeadList);
		});
		ExcelUtil.writeExcel(UsersOperationsOverviewVO.class, formTitleName, title, usersOperationsOverviewVOS, headList, response);
	}

	/**
	 * 导出XX用户操作统计列表Excel文件
	 *
	 * @param params   用户操作概况查询参数
	 * @param response
	 * @return
	 */
	@Override
	public void exportUserOperationsStatistics(UsersOperationsParams params, HttpServletResponse response) throws IOException {
		//取消分页
		params.setPageNum(1);
		params.setPageSize(-1);
		PageDataInfo pageDataInfo = queryUserOperationsStatistics(params);

		List<UserOperationsStatisticsVO> userOperationsStatisticsVOS = BeanUtils.cast(pageDataInfo.getData());
		//回填序号
		int index = 1;
		for (UserOperationsStatisticsVO vo : userOperationsStatisticsVOS) {
			vo.setId(index++);
		}
		//excel主标题
		String title = "操作统计";
		List<String> titleParams = new ArrayList<>();
		titleParams.add(title);
		ConfSystem system = remoteSystemService.getSystemById(params.getSystemId()).getData();
		if (ObjectUtil.isNotEmpty(system)) {
			titleParams.add(system.getName());
		}
//        titleParams.add(searchOptionService.queryOperatorName(params.getUserIdentify())); todo
		//回填业务状态
		switch (params.getBusinessStatus()) {
			case 0:
				titleParams.add("访问量");
				break;
			case 1:
				titleParams.add("告警访问量");
				break;
			case 3:
				titleParams.add("失败访问量");
		}
		String formTitleName = ExcelTitleUtils.formTitleName(titleParams, params.getStartTime(), params.getEndTime());
		//列标题
		List<List<String>> headList = new ArrayList<>();
		List<String> titleList = Arrays.asList("序号", "业务名称", "访问量", "告警访问量", "失败访问量");
		titleList.forEach(s -> {
			List<String> childHeadList = new ArrayList<>();
			childHeadList.add(formTitleName);
			childHeadList.add(s);
			headList.add(childHeadList);
		});
		ExcelUtil.writeExcel(UserOperationsStatisticsVO.class, formTitleName, title, userOperationsStatisticsVOS, headList, response);
	}

	/**
	 * 导出XX用户XX业务操作详情列表Excel文件
	 *
	 * @param params   用户操作概况查询参数
	 * @param response
	 */
	@Override
	public void exportUserBusinessOperationsDetail(UsersOperationsParams params, HttpServletResponse response) throws IOException {
		//取消分页
		params.setPageNum(1);
		params.setPageSize(-1);

		PageDataInfo pageDataInfo = queryUserBusinessOperationsDetail(params);
		List<UserBusinessOperationsDetailVO> userBusinessOperationsDetailVOS = BeanUtils.cast(pageDataInfo.getData());
		int index = 1;
		for (UserBusinessOperationsDetailVO vo : userBusinessOperationsDetailVOS) {
			DecimalFormat df = new DecimalFormat("0.00");
			double dealTime = Double.parseDouble(vo.getDealTime());
			double second = 0;
			int minute = 0;
			double ms = 0;
			if (dealTime >= 60000000) {
				second = dealTime / 1000000;
				minute = (int) second / 60;
				second = second - minute * 60;
				vo.setDealTime(minute + "分" + df.format(second) + "秒");
			} else if (dealTime >= 1000000) {
				second = dealTime / 1000000;
				vo.setDealTime(df.format(second) + "秒");
			} else {
				ms = dealTime / 1000;
				vo.setDealTime(df.format(ms) + "毫秒");
			}
			vo.setId(index++);
		}
		//excel主标题
		String title = "操作详情";
		List<String> titleParams = new ArrayList<>();
		titleParams.add(title);
		ConfSystem system = remoteSystemService.getSystemById(params.getSystemId()).getData();
		if (ObjectUtil.isNotEmpty(system)) {
			titleParams.add(system.getName());
		}
		String businessName = remoteBusinessService.getBusinessByBusinessCode(params.getBusinessCode()).getData().getName();
		titleParams.add(businessName);
//        titleParams.add(searchOptionService.queryOperatorName(params.getUserIdentify()));
		//回填业务状态
		switch (params.getBusinessStatus()) {
			case 0:
				titleParams.add("访问量");
				break;
			case 1:
				titleParams.add("告警访问量");
				break;
			case 3:
				titleParams.add("失败访问量");
		}
		String formTitleName = ExcelTitleUtils.formTitleName(titleParams, params.getStartTime(), params.getEndTime());
		//列标题
		List<List<String>> headList = new ArrayList<>();
		List<String> titleList = Arrays.asList("序号", "请求IP", "自定义返回码", "开始时间", "结束时间", "办理时长", "业务状态", "完整性", "告警数", "专属指标");
		titleList.forEach(s -> {
			List<String> childHeadList = new ArrayList<>();
			childHeadList.add(formTitleName);
			childHeadList.add(s);
			headList.add(childHeadList);
		});
		ExcelUtil.writeExcel(UserBusinessOperationsDetailVO.class, formTitleName, title, userBusinessOperationsDetailVOS, headList, response);
	}

	/**
	 * 查询用户统计数据
	 *
	 * @param startTime    开始时间
	 * @param endTime      结束时间
	 * @param systemId     系统ID
	 * @param businessCode 业务编码
	 * @return 统计数
	 */
	@Override
	public int queryBusiUserCount(String startTime, String endTime, int systemId, String businessCode) {
		try {
			BaseSearch search = new BaseSearch();
			search.setStartTime(startTime);
			search.setEndTime(endTime);
			return userOperationsMapper.queryBusiUserCount(systemId, businessCode, search);
		} catch (Exception e) {
			log.error("查询用户统计数据异常：", e);
			return 0;
		}
	}

	/**
	 * 查询异常用户统计数据
	 *
	 * @param startTime    开始时间
	 * @param endTime      结束时间
	 * @param systemId     系统ID
	 * @param businessCode 业务编码
	 * @return 统计数
	 */
	@Override
	public int queryBusiUserExcepitonCount(String startTime, String endTime, int systemId, String businessCode) {
		try {

			BaseSearch search = new BaseSearch();
			search.setStartTime(startTime);
			search.setEndTime(endTime);

			return userOperationsMapper.queryBusiUserExcepitonCount("ads_busi_detail_user_stat_m", search, systemId, businessCode);
		} catch (Exception e) {
			log.error("查询异常用户统计数据异常：", e);
			return 0;
		}
	}
}
